#ifndef	__CXX_VIEWS_GRPH_CANVAS_H__
#define	__CXX_VIEWS_GRPH_CANVAS_H__

#include "grphbsc.h"
#include "font.h"

namespace visgrph
{

class bitmap;
class canvas;
class pen_impl;
class canvas_impl;

struct rect
{
	int left;
	int top;
	int width;
	int height;
};

class GRPH_EXPORT_API color
{
public:

	color() : m_color(255 << 24) {}
	color(const color& c) : m_color(c.m_color) {}

	color& operator=(const color& c)
	{
		if (this != &c)
			m_color = c.m_color;
		return *this;
	}

	color(uint r, uint g, uint b)
		: m_color((0xFF << 24) | ((b & 0xFF) << 16) | ((g & 0xFF) << 8) | (r & 0xFF))
	{
	}

	color(float r, float g, float b)
	{
		if (r > 1.) r = 1.;
		if (g > 1.) g = 1.;
		if (b > 1.) b = 1.;
		m_color = (255 << 24) | (uint(b * 255) << 16)
			| (uint(g * 255) << 8) | (uint(r * 255));
	}

	color(uint r, uint g, uint b, uint a)
		: m_color(((a & 0xFF) << 24) | ((b & 0xFF) << 16)
		| ((g & 0xFF) << 8) | (r & 0xFF))
	{
	}

	~color() {}
	uint value(void) { return m_color; }
	uint red(void) { return m_color & 0xFF; }
	uint green(void) { return (m_color >> 8) & 0xFF; }
	uint blue(void) { return (m_color >> 16) & 0xFF; }
	uint alpha(void) { return (m_color >> 24); }

private:
	unsigned int m_color;
};

enum pen_style
{
	pen_style_unknown = 0,
	pen_style_solid,

	// if a dot line pen style is specified,
	// the user need to specify the pattern, or
	// the system will select a default one
	pen_style_dotline,
};

enum pen_cap_type
{
	pen_cap_type_unknown = -1,
	pen_cap_type_flat,
	pen_cap_type_round,
};

enum pen_join_type
{
	pen_join_type_unknown = -1,
	pen_join_type_no_join,
	pen_join_type_miter,
	pen_join_type_round,
	pen_join_type_accurate,
};

class GRPH_EXPORT_API pen
{
	friend class canvas;
public:
	pen();
	pen(const pen& p);
	pen(float width, color c, pen_style ps = pen_style_solid);
	~pen();

	// set and get cap/join type
	pen_cap_type cap_type(pen_cap_type type = pen_cap_type_unknown);
	pen_join_type join_type(pen_join_type type = pen_join_type_unknown);

private:
	pen_impl*	m_pen;
};

class GRPH_EXPORT_API canvas
{
public:
	canvas();
	canvas(const canvas&);
	canvas(const canvas&, int dx, int dy, int w, int h);
	canvas(const bitmap&);
	canvas(const bitmap&, int dx, int dy, int w, int h);
	canvas& operator=(const canvas&);
	canvas(uint width, uint height);
	~canvas();

public:
	int width(void) const;
	int height(void) const;

public:
	// select object
	bool select_object(const pen& p);
	bool select_object(const font& f);
	bool select_object(fontinfo* finfo, int fwidth, int fheight);

	// clipping
	bool reset_clipping(void);
	bool add_clipbox(int left, int top, int width, int height);
	bool add_clipbox(const rect& r);

public:
	// clear the canvas
	// alpha channel is ommitted
	void clear(color c);

	// basic functions
	void hline(uint x, uint y, uint length, color c);
	void vline(uint x, uint y, uint height, color c);
	void rectangle(uint x, uint y, uint width, uint height, color c);
	void box(uint x, uint y, uint width, uint height, color c);

	// text render
	void textout(float x, float y, formatted_text text, color c, int sz = -1);

	void line(float x1, float y1, float x2, float y2);

private:
	canvas_impl* impl;
};

};	// namespace visgrph

#endif	// __CXX_VIEWS_GRPH_CANVAS_H__
/* EOF */

